# -*- coding: utf-8 -*-
"""
Web应用异常处理

定义Web层特有的异常类型和错误代码，用于：
- 统一API错误响应格式
- 标准化错误代码
- 提供详细的错误信息
"""

from typing import Any, Dict, Optional
from fastapi import HTTPException, status


class ErrorCode:
    """错误代码常量"""
    
    # 通用错误
    SUCCESS = "SUCCESS"
    UNKNOWN_ERROR = "UNKNOWN_ERROR"
    INTERNAL_ERROR = "INTERNAL_ERROR"
    VALIDATION_ERROR = "VALIDATION_ERROR"
    
    # 认证和授权错误
    UNAUTHORIZED = "UNAUTHORIZED"
    FORBIDDEN = "FORBIDDEN"
    TOKEN_EXPIRED = "TOKEN_EXPIRED"
    TOKEN_INVALID = "TOKEN_INVALID"
    LOGIN_FAILED = "LOGIN_FAILED"
    PERMISSION_DENIED = "PERMISSION_DENIED"
    
    # 资源错误
    NOT_FOUND = "NOT_FOUND"
    ALREADY_EXISTS = "ALREADY_EXISTS"
    CONFLICT = "CONFLICT"
    
    # 业务错误
    BUSINESS_ERROR = "BUSINESS_ERROR"
    DATA_ERROR = "DATA_ERROR"
    OPERATION_FAILED = "OPERATION_FAILED"
    
    # 请求错误
    BAD_REQUEST = "BAD_REQUEST"
    INVALID_PARAMETER = "INVALID_PARAMETER"
    MISSING_PARAMETER = "MISSING_PARAMETER"
    
    # 文件错误
    FILE_NOT_FOUND = "FILE_NOT_FOUND"
    FILE_TOO_LARGE = "FILE_TOO_LARGE"
    FILE_TYPE_NOT_ALLOWED = "FILE_TYPE_NOT_ALLOWED"
    
    # 数据库错误
    DATABASE_ERROR = "DATABASE_ERROR"
    CONNECTION_ERROR = "CONNECTION_ERROR"
    
    # 外部服务错误
    EXTERNAL_SERVICE_ERROR = "EXTERNAL_SERVICE_ERROR"
    NETWORK_ERROR = "NETWORK_ERROR"


class CRMException(Exception):
    """CRM业务异常基类"""
    
    def __init__(
        self,
        message: str,
        error_code: str = ErrorCode.BUSINESS_ERROR,
        status_code: int = status.HTTP_400_BAD_REQUEST,
        details: Optional[Dict[str, Any]] = None
    ):
        self.message = message
        self.error_code = error_code
        self.status_code = status_code
        self.details = details or {}
        super().__init__(self.message)


class AuthenticationError(CRMException):
    """认证异常"""
    
    def __init__(self, message: str = "认证失败", details: Optional[Dict[str, Any]] = None):
        super().__init__(
            message=message,
            error_code=ErrorCode.UNAUTHORIZED,
            status_code=status.HTTP_401_UNAUTHORIZED,
            details=details
        )


class AuthorizationError(CRMException):
    """授权异常"""
    
    def __init__(self, message: str = "权限不足", details: Optional[Dict[str, Any]] = None):
        super().__init__(
            message=message,
            error_code=ErrorCode.FORBIDDEN,
            status_code=status.HTTP_403_FORBIDDEN,
            details=details
        )


class NotFoundError(CRMException):
    """资源未找到异常"""
    
    def __init__(self, message: str = "资源未找到", details: Optional[Dict[str, Any]] = None):
        super().__init__(
            message=message,
            error_code=ErrorCode.NOT_FOUND,
            status_code=status.HTTP_404_NOT_FOUND,
            details=details
        )


class ConflictError(CRMException):
    """资源冲突异常"""
    
    def __init__(self, message: str = "资源冲突", details: Optional[Dict[str, Any]] = None):
        super().__init__(
            message=message,
            error_code=ErrorCode.CONFLICT,
            status_code=status.HTTP_409_CONFLICT,
            details=details
        )


class ValidationError(CRMException):
    """数据验证异常"""
    
    def __init__(self, message: str = "数据验证失败", details: Optional[Dict[str, Any]] = None):
        super().__init__(
            message=message,
            error_code=ErrorCode.VALIDATION_ERROR,
            status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
            details=details
        )


class BusinessError(CRMException):
    """业务逻辑异常"""
    
    def __init__(self, message: str, details: Optional[Dict[str, Any]] = None):
        super().__init__(
            message=message,
            error_code=ErrorCode.BUSINESS_ERROR,
            status_code=status.HTTP_400_BAD_REQUEST,
            details=details
        )


# 别名，为了兼容性
BusinessLogicError = BusinessError


class DatabaseError(CRMException):
    """数据库异常"""
    
    def __init__(self, message: str = "数据库操作失败", details: Optional[Dict[str, Any]] = None):
        super().__init__(
            message=message,
            error_code=ErrorCode.DATABASE_ERROR,
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            details=details
        )


class ExternalServiceError(CRMException):
    """外部服务异常"""
    
    def __init__(self, message: str = "外部服务调用失败", details: Optional[Dict[str, Any]] = None):
        super().__init__(
            message=message,
            error_code=ErrorCode.EXTERNAL_SERVICE_ERROR,
            status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
            details=details
        )


class FileError(CRMException):
    """文件操作异常"""
    
    def __init__(self, message: str, details: Optional[Dict[str, Any]] = None):
        super().__init__(
            message=message,
            error_code=ErrorCode.FILE_NOT_FOUND,
            status_code=status.HTTP_400_BAD_REQUEST,
            details=details
        )


def create_http_exception(
    status_code: int,
    message: str,
    error_code: str = ErrorCode.UNKNOWN_ERROR,
    details: Optional[Dict[str, Any]] = None
) -> HTTPException:
    """创建HTTP异常"""
    return HTTPException(
        status_code=status_code,
        detail={
            "error": True,
            "error_code": error_code,
            "message": message,
            "details": details or {}
        }
    )


def handle_database_error(e: Exception) -> DatabaseError:
    """处理数据库异常"""
    error_msg = str(e)
    
    # 常见数据库错误映射
    if "duplicate key" in error_msg.lower():
        return ConflictError("数据已存在", {"原因": "违反唯一性约束"})
    elif "foreign key" in error_msg.lower():
        return ValidationError("数据关联错误", {"原因": "违反外键约束"})
    elif "not null" in error_msg.lower():
        return ValidationError("必填字段缺失", {"原因": "违反非空约束"})
    else:
        return DatabaseError(f"数据库操作失败: {error_msg}")